热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

升序|都会_Hive与优化方法

篇首语:本文由编程笔记#小编为大家整理,主要介绍了Hive与优化方法相关的知识,希望对你有一定的参考价值。Hive与优化方法

篇首语:本文由编程笔记#小编为大家整理,主要介绍了Hive与优化方法相关的知识,希望对你有一定的参考价值。



Hive与优化方法


文章目录


  • Hive与优化方法
  • 一、Hive概念
  • 二、Hive架构
  • 三、Hive与数据库的比较
  • 四、Hive中一些重要的概念
    • 4.1 内部表和外部表
    • 4.2 分区表
    • 4.3 Hive排序关键字
    • 4.4 Hive分桶
    • 4.5 三种排序窗函数的区别
    • 4.6 Hive解析MR的Reduce数量的确定
    • 4.7 Hive的存储格式

  • 五、Hive调优
    • 5.1 部分场景下尽可能避免启用MR
    • 5.2 表的优化
    • 5.3 数据倾斜优化
    • 5.3 其他优化




Java、大数据开发学习要点(持续更新中…)




一、Hive概念

  Hive是基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张表,并提供类SQL查询功能。其本质是,将HQL转化成MapReduce程序。底层数据存储在HDFS上,由于延迟较大所以一般适用于离线大批量的数据计算和分析。


二、Hive架构


  1. 用户接口Client:
    CLI(hive shell)、JDBC/ODBC(java访问hive)、WEBUI(浏览器访问hive)
  2. 元数据Metastore:
    元数据包括:表名、表所属的数据库(默认是default)、表的拥有者、列/分区字段、表的类型(是否是外部表)、表的数据所在目录等;默认存储在自带的derby数据库中,推荐使用MySQL存储Metastore
  3. Hadoop:
    使用HDFS进行存储,使用MapReduce进行计算。
  4. 驱动器Driver(Hive执行过程):
    • 解析器(SQL Parser):将SQL字符串(shell命令行、JDBC、Web)转换成抽象语法树AST,这一步一般都用第三方工具库完成,比如antlr;对AST进行语法分析,根据MetaStore中的元数据信息判断SQL语句的合法性,比如表是否存在、字段是否存在、SQL语义是否有误。
    • 编译器(Physical Plan):将抽象语法树编译生成逻辑执行计划。
    • 优化器(Query Optimizer):对逻辑执行计划进行优化。
    • 执行器(Execution):把逻辑执行计划转换成可以运行的物理计划存储在HDFS上由计算引擎进行调用。对于Hive来说,就是MR/Spark任务。

三、Hive与数据库的比较

  Hive 和数据库除了拥有类似的查询语言,再无类似之处。其实记住Hive是数仓工具就可以将其与数据库区别开来。


  • Hive与传统数据库的区别:

  1. 数据更新:由于Hive是针对数据仓库应用设计的,而数据仓库的内容是读多写少的。因此,Hive中不建议对数据的改写,所有的数据都是在加载的时候确定好的。而数据库中的数据通常是需要经常进行更新。
  2. 数据查询:传统数据库数据由于索引的存在,在数据量较小的情况下查询较快,并且自己提供执行引擎。而Hive数据查询是整表或者分区表的扫描,只有在大数据情况下分布式运算才有优势,依靠MR或Spark来执行。
  3. 数据存储:Hive数据存储没有固定的格式,用户可以自己指定存储的格式(Parquet、SequenceFile等),并自己指定压缩格式(Snappy、ORC)。数据库的存储引擎定义了自己的存储格式。

  • Hive与HBase的区别:
    其实没有什么可以比较的。HBase是一个分布式列簇式存储KV数据库,Hive是一个数仓工具。Hive擅长于大数据离线计算和分析,而HBase则是提供快速数据写入和查询的数据库应用在实时查询的场景。

四、Hive中一些重要的概念

4.1 内部表和外部表

  内部表生命周期是受Hive控制的,删除内部表则数据和元数据都会被删除;将数据导入外部表,数据并不会移动,即使删除外部表,只是删除外部表元数据,而原来的数据还是会存在



使用的例子,HDFS定期收到用户行为日志文件,在日志文件上建立外部表,中间表和结果表则以内部表的形式存储。



4.2 分区表

  分区表实际上就是对应一个HDFS文件系统上的独立的文件夹,该文件夹下是该分区所有的数据文件。Hive根据某列或者某些列的值(这些列在表中并不真实存在)将数据分区,放在表文件夹下不同子文件夹中存储。Hive中的分区就是分目录,把一个大的数据集根据业务需要分割成小的数据集。


  • 静态分区和动态分区:

  1. 静态分区:在建表中指定分区条件,数据导入或者插入时需要指定分区。
  2. 动态分区:按照某个或某些字段的值不同自动地进行分区,底层实际是利用MapReduce的mutipleOutputs(根据条件判断,将结果写入不同目录不同文件)。
  3. 静态分区必须在动态分区前。

  • 分区的注意事项:
    Hive分区过多,导致每个分区的文件小,会导致HDFS小文件过多的问题
    (1)小文件数量过多造成NameNode负担过大。
    (2)Hive运行Mapreduce时,每个block对应一个切片,而小文件则会直接对应一个map任务,使得map任务过多使得运行效率低下(Yarn频繁申请销毁容器)。

4.3 Hive排序关键字


  1. ORDER BY:全局排序,强制只有一个Reducer,但是当数据规模较大时,会导致消耗较长的计算时间。

  2. SORT BY:局部排序,每个task内部排序,使得reduce结果都是局部有序的

  3. DISTRIBUTE BY:类似MR中的Partition分区器,根据某一列进行分区。使用DISTRIBUTE BY+SORT BY来实现分桶排序查询,如:

    hive (default)> set mapreduce.job.reduces=3;
    --根据col1进行分区,再根据col2进行分区内的降序排序
    hive (default)> select col1,col2
    from emp distribute by col1 sort by col2 desc;

  4. CLUSTER BY:当DISTRIBUTE BY和SORT BY字段相同时,可以使用CLUSTER BY代替,但只能升序排列。


4.4 Hive分桶

  对Hive表分桶可以将表中数据按分桶键的哈希值散列到多个文件中,这些小文件称为桶。



表分区是用不同的子文件夹管理不同的数据;而表分桶用不同的文件管理不同的数据。



  • 分桶的好处:

  1. join两个相同分桶划分的表时可以使用map-side join,优化join查询
  2. 根据某些列进行分桶可以使Hive查询时利用分桶的结构加快查询效率
  3. 对于非常大的数据集,有时用户需要使用的是一个具有代表性的查询结果而不是全部结果。Hive可以通过对表进行抽样来满足这个需求。而分桶的结构恰好满足抽样所需的数据结构,使得抽样更加高效。

4.5 三种排序窗函数的区别


  • RANK() n个排序相同时排名会重复,但下一个排名会跳跃至n个名次开始。(跳跃)
  • DENSE_RANK() n个排序相同时排名会重复,但下一个排名继续上一个排名加1开始。(连续)
  • ROW_NUMBER() 会根据顺序依次编号。

4.6 Hive解析MR的Reduce数量的确定

hive有两个参数设定:hive.exec.reducers.bytes.per.reducer(下称参数1)和hive.exec.reducers.max(下称参数2)

hive解析成MR后的Reduce数量则是N = min(参数2,任务总数据量/参数1),默认参数1是1G。


4.7 Hive的存储格式


  • text:默认存储格式,普通的文本文件,数据不压缩,磁盘的开销比较大,分析开销大。
  • Parquet:一种行式存储格式,具有很好的压缩性能;同时可以减少大量的表扫描和反序列化的时间。
  • ORC:Hive/Spark都支持这种存储格式,它存储的方式是数据按行分块,每个块按列存储,其中每个块都存储有一个索引。特点是数据压缩率非常高。

五、Hive调优

5.1 部分场景下尽可能避免启用MR

由于MapReduce的启动任务调度通常在数据集小的情况下耗时比job本身时间要长。所以Hive在有些场景下可以尽量避免启动MR来执行任务。比如数据抓取(Fetch)在全表数据获取、字段查找、limit查找的情况下可以不走MapReduce;再比如数据集较小的情况下,开启本地模式单机处理所有任务也能比走集群计算得到更好的时间效率。


5.2 表的优化


  • 小表JOIN大表:

  1. JOIN有个特点是其中一个表需要作为全量读取的表先加载至内存,所以小表写在JOIN左边(当然这点Hive的开发者已经对此进行了优化)
  2. 小表JOIN大表的情况下,尽量使用map-side join,将小表广播到大表所在的map任务中,以减少小表shuffler所带来的IO开销。

  • 大表JOIN大表:

  1. 要注意的是大表的数据量基本都比较大,JOIN容易出现reducer的OOM,所以要注意JOIN前数据的过滤与某些空key数据产生的数据倾斜问题(随机赋值)

  • 替换COUNT DISTINCT去重统计
    COUNT DISTINCT通过一个Reducer来完成去重统计,在数据量巨大的场景下效率低下。将COUNT DISTINCT用两阶段进行替换:先GROUP BY再开启一个任务进行COUNT

  • 避免笛卡尔积
    表的无条件JOIN(没有指定ON条件,或条件无效),Hive只能用一个Reducer完成,效率极其低下。

  • 行过滤
    在表的JOIN关联中,将附表的过滤作为子查询写在ON条件之前,否则会导致先关联再过滤的问题产生。


5.3 数据倾斜优化


  1. map-side join来缓解数据倾斜问题
    如果不指定MapJoin或者不符合MapJoin的条件,那么Hive解析器会将Join操作转换成Common Join,即:在Reduce阶段完成join。容易发生数据倾斜。可以用Map-side Join把小表全部加载到内存在Map端进行join,避免Reducer处理。(参数设置set hive.auto.convert.join = true;默认是true)

  2. Group by开启Map端预聚合
    默认情况下,Map阶段同一Key数据分发给一个Reducer,当一个key数据过大时就倾斜了。并不是所有的聚合操作都需要在Reduce端完成,很多聚合操作都可以先在Map端进行部分聚合,最后在Reduce端得出最终结果。两个参数hive.map.aggr = true(默认) 和 hive.groupby.skewindata = true(非默认),分别是开启Map端预聚合和数据倾斜时进行负载均衡。



    当选项设定为 true,生成的查询计划会有两个MR Job。第一个MR Job中,Map的输出结果会随机分布到Reduce中,每个Reduce做部分聚合操作,并输出结果,这样处理的结果是相同的Group By Key有可能被分发到不同的Reduce中,从而达到负载均衡的目的;第二个MR Job再根据预处理的数据结果按照Group By的Key分布到Reducer中(这个过程可以保证相同的Key被分布到同一个Reducer中),最后完成最终的聚合操作。


  3. 合理设置Map任务数和Reduce任务数


  • 合理的Map任务数:


    1. 每个小文件对应一个Map任务是不明智的,导致Map任务数过多,且任务启动调度的时间远大于任务逻辑执行的时间。
    2. 每个Map的大小接近128M呢?则会使得单个Map任务的执行时间过长。

    所以,Map任务需要按照场景进行调整,小文件多的情况下减少Map任务并设置Hive的InputFormat为CombineHiveInputFormat;而文件较大的情况下,增加Map数量来分担单文件大数据量的计算压力

  • 合理的Reduce任务数:

    与Map任务类似,Reducer数量也要合理,太多增大调度资源和小文件的产生,过少单个Reduce任务执行时间过长。


5.3 其他优化


  1. 并行执行:
    Hive会将一个查询转化成一个或者多个阶段。这样的阶段可以是MapReduce阶段、抽样阶段、合并阶段、limit阶段。或者Hive执行过程中可能需要的其他阶段。默认情况下,Hive一次只会执行一个阶段。不过,某个特定的job可能包含众多的阶段,而这些阶段可能并非完全互相依赖的,也就是说有些阶段是可以并行执行的,这样可能使得整个job的执行时间缩短。不过,如果有更多的阶段可以并行执行,那么job可能就越快完成。

  2. 严格模式:



    1. 对于分区表,除非where语句中含有分区字段过滤条件来限制范围,否则不允许执行。换句话说,就是用户不允许扫描所有分区。进行这个限制的原因是,通常分区表都拥有非常大的数据集,而且数据增加迅速。没有进行分区限制的查询可能会消耗令人不可接受的巨大资源来处理这个表。
    2. 对于使用了order by语句的查询,要求必须使用limit语句。因为order by为了执行排序过程会将所有的结果数据分发到同一个Reducer中进行处理,强制要求用户增加这个LIMIT语句可以防止Reducer额外执行很长一段时间。
    3. 限制笛卡尔积的查询。对关系型数据库非常了解的用户可能期望在执行JOIN查询的时候不使用ON语句而是使用WHERE语句,这样关系数据库的执行优化器就可以高效地将WHERE语句转化成那个ON语句。不幸的是,Hive并不会执行这种优化,因此,如果表足够大,那么这个查询就会出现不可控的情况。

  3. JVM重用:

    JVM重用是Hadoop调优参数的内容,其对Hive的性能具有非常大的影响,特别是对于很难避免小文件的场景或task特别多的场景,这类场景大多数任务执行时间都很短

  4. 合理压缩:

    比如使用Parquet列式存储数据,这种格式按列存储数据,没列数据类型相同,天然对压缩友好,建议可以使用Parquet(ORC)存储格式+Snappy压缩格式的组合


推荐阅读
  • 本文介绍了高校天文共享平台的开发过程中的思考和规划。该平台旨在为高校学生提供天象预报、科普知识、观测活动、图片分享等功能。文章分析了项目的技术栈选择、网站前端布局、业务流程、数据库结构等方面,并总结了项目存在的问题,如前后端未分离、代码混乱等。作者表示希望通过记录和规划,能够理清思路,进一步完善该平台。 ... [详细]
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
  • 如何使用Java获取服务器硬件信息和磁盘负载率
    本文介绍了使用Java编程语言获取服务器硬件信息和磁盘负载率的方法。首先在远程服务器上搭建一个支持服务端语言的HTTP服务,并获取服务器的磁盘信息,并将结果输出。然后在本地使用JS编写一个AJAX脚本,远程请求服务端的程序,得到结果并展示给用户。其中还介绍了如何提取硬盘序列号的方法。 ... [详细]
  • 本文介绍了C#中数据集DataSet对象的使用及相关方法详解,包括DataSet对象的概述、与数据关系对象的互联、Rows集合和Columns集合的组成,以及DataSet对象常用的方法之一——Merge方法的使用。通过本文的阅读,读者可以了解到DataSet对象在C#中的重要性和使用方法。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • [译]技术公司十年经验的职场生涯回顾
    本文是一位在技术公司工作十年的职场人士对自己职业生涯的总结回顾。她的职业规划与众不同,令人深思又有趣。其中涉及到的内容有机器学习、创新创业以及引用了女性主义者在TED演讲中的部分讲义。文章表达了对职业生涯的愿望和希望,认为人类有能力不断改善自己。 ... [详细]
  • 知识图谱——机器大脑中的知识库
    本文介绍了知识图谱在机器大脑中的应用,以及搜索引擎在知识图谱方面的发展。以谷歌知识图谱为例,说明了知识图谱的智能化特点。通过搜索引擎用户可以获取更加智能化的答案,如搜索关键词"Marie Curie",会得到居里夫人的详细信息以及与之相关的历史人物。知识图谱的出现引起了搜索引擎行业的变革,不仅美国的微软必应,中国的百度、搜狗等搜索引擎公司也纷纷推出了自己的知识图谱。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 基于事件驱动的并发编程及其消息通信机制的同步与异步、阻塞与非阻塞、IO模型的分类
    本文介绍了基于事件驱动的并发编程中的消息通信机制,包括同步和异步的概念及其区别,阻塞和非阻塞的状态,以及IO模型的分类。同步阻塞IO、同步非阻塞IO、异步阻塞IO和异步非阻塞IO等不同的IO模型被详细解释。这些概念和模型对于理解并发编程中的消息通信和IO操作具有重要意义。 ... [详细]
  • 本文介绍了在Mac上搭建php环境后无法使用localhost连接mysql的问题,并通过将localhost替换为127.0.0.1或本机IP解决了该问题。文章解释了localhost和127.0.0.1的区别,指出了使用socket方式连接导致连接失败的原因。此外,还提供了相关链接供读者深入了解。 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • Tomcat/Jetty为何选择扩展线程池而不是使用JDK原生线程池?
    本文探讨了Tomcat和Jetty选择扩展线程池而不是使用JDK原生线程池的原因。通过比较IO密集型任务和CPU密集型任务的特点,解释了为何Tomcat和Jetty需要扩展线程池来提高并发度和任务处理速度。同时,介绍了JDK原生线程池的工作流程。 ... [详细]
  • Java验证码——kaptcha的使用配置及样式
    本文介绍了如何使用kaptcha库来实现Java验证码的配置和样式设置,包括pom.xml的依赖配置和web.xml中servlet的配置。 ... [详细]
  • 高质量SQL书写的30条建议
    本文提供了30条关于优化SQL的建议,包括避免使用select *,使用具体字段,以及使用limit 1等。这些建议是基于实际开发经验总结出来的,旨在帮助读者优化SQL查询。 ... [详细]
  • 使用Ubuntu中的Python获取浏览器历史记录原文: ... [详细]
author-avatar
manassatromble
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有